---
title: Маршрутизация
description: Введение в маршрутизацию с Astro.
i18nReady: true
---
import { FileTree } from '@astrojs/starlight/components';
import RecipeLinks from "~/components/RecipeLinks.astro"
import Since from '~/components/Since.astro'
import ReadMore from '~/components/ReadMore.astro'

Astro использует **маршрутизацию на основе файлов** для генерации URL-адресов ваших сборок на основе схемы расположения файлов в каталоге `src/pages/` вашего проекта.

## Навигация между страницами

Astro использует стандартные HTML-элементы [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) для навигации между маршрутами. Нет специфического для фреймворка компонента `<Link>`.

```astro title="src/pages/index.astro"
<p>Read more <a href="/about/">about</a> Astro!</p>
```

## Статические маршруты

[Компоненты страниц](/ru/basics/astro-pages/) `.astro`, а также Markdown и MDX файлы (`.md`, `.mdx`) в директории `src/pages/` **автоматически становятся страницами вашего сайта**. Маршрут каждой страницы соответствует ее пути и имени файла в каталоге `src/pages/`.

```diff
# Пример: Статические маршруты
src/pages/index.astro        -> mysite.com/
src/pages/about.astro        -> mysite.com/about
src/pages/about/index.astro  -> mysite.com/about
src/pages/about/me.astro     -> mysite.com/about/me
src/pages/posts/1.md         -> mysite.com/posts/1
```

:::tip
В проекте Astro нет отдельного "конфигурационного файла маршрутизации"! Когда вы добавляете файл в директорию `src/pages/`, для вас автоматически создается новый маршрут. В статических сборках вы можете настроить формат вывода файлов с помощью опции [`build.format`](/ru/reference/configuration-reference/#buildformat).
:::

## Динамические маршруты

В имени файла страницы Astro могут быть указаны параметры динамического маршрута для создания нескольких подходящих страниц. Например, `src/pages/authors/[author].astro` генерирует биографическую страницу для каждого автора в вашем блоге. `author` становится _параметром_, к которому вы можете обращаться внутри страницы.

В стандартном режиме статического вывода Astro эти страницы генерируются во время сборки, поэтому вы должны заранее определить список `авторов`, которые получат соответствующий файл. В режиме SSR страница будет генерироваться по запросу для любого маршрута, который соответствует.

### Статический (SSG) режим

Поскольку все маршруты должны быть определены во время сборки, динамический маршрут должен экспортировать функцию `getStaticPaths()`, которая возвращает массив объектов со свойством `params`. Каждый из этих объектов будет генерировать соответствующий маршрут.

`[dog].astro` определяет динамический параметр `dog` в своем имени, поэтому объекты, возвращаемые `getStaticPaths()`, должны включать `dog` в свои `params`. Затем страница может получить доступ к этому параметру с помощью `Astro.params`.

```astro title="src/pages/dogs/[dog].astro"
---
export function getStaticPaths() {
  return [
    {params: {dog: 'clifford'}},
    {params: {dog: 'rover'}},
    {params: {dog: 'spot'}},
  ];
}

const { dog } = Astro.params;
---
<div>Good dog, {dog}!</div>
```

В результате будут сгенерированы три страницы: `/dogs/clifford`, `/dogs/rover` и `/dogs/spot`, каждая из которых отображает соответствующее имя собаки.

Имя файла может включать несколько параметров, которые должны быть включены в объекты `params` в `getStaticPaths()`:


```astro title="src/pages/[lang]-[version]/info.astro"
---
export function getStaticPaths () {
 return [
    {params: {lang: 'en', version: 'v1'}},
    {params: {lang: 'fr', version: 'v2'}},
  ];
}

const { lang, version } = Astro.params;
---
...
```

В результате будут сгенерированы `/en-v1/info` и `/fr-v2/info`.

Параметры могут быть включены в отдельные части пути. Например, файл `src/pages/[lang]/[version]/info.astro` с тем же `getStaticPaths()`, что и выше, сгенерирует маршруты `/en/v1/info` и `/fr/v2/info`.

<ReadMore>Узнайте больше о [`getStaticPaths()`](/ru/reference/api-reference/#getstaticpaths).</ReadMore>


<RecipeLinks slugs={["ru/recipes/i18n"]} />

#### Rest параметры

Если вам нужна большая гибкость в маршрутизации URL, вы можете использовать [rest параметры](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) (`[...path]`) в имени файла `.astro` для сопоставления путей файлов любой глубины:

```astro title="src/pages/sequences/[...path].astro"
---
export function getStaticPaths() {
  return [
    {params: {path: 'one/two/three'}},
    {params: {path: 'four'}},
    {params: {path: undefined }}
  ]
}

const { path } = Astro.params;
---
...
```

Это сгенерирует `/sequences/one/two/three`, `/sequences/four` и `/sequences`. (Установка параметра rest в значение `undefined` позволяет ему соответствовать странице верхнего уровня).

Параметры rest можно использовать с **другими именованными параметрами**. Например, просмотрщик файлов GitHub может быть представлен следующим динамическим маршрутом:

```
/[org]/[repo]/tree/[branch]/[...file]
```
В этом примере запрос на `/withastro/astro/tree/main/docs/public/favicon.svg` будет разбит на следующие именованные параметры:

```js
{
	org: 'withastro',
	repo: 'astro',
	branch: 'main',
	file: 'docs/public/favicon.svg'
}
```

#### Пример: Динамические страницы на нескольких уровнях

В следующем примере параметр rest (`[...slug]`) и функция [`props`](/ru/reference/api-reference/#передача-данных-с-помощью-props) в `getStaticPaths()` генерируют страницы для слагов разной глубины.


```astro title="src/pages/[...slug].astro"
---
export async function getStaticPaths() {
  const pages = [
    {
      slug: undefined,
      title: "Astro Store",
      text: "Welcome to the Astro store!",
    },
    {
      slug: "products",
      title: "Astro products",
      text: "We have lots of products for you",
    },
    {
      slug: "products/astro-handbook",
      title: "The ultimate Astro handbook",
      text: "If you want to learn Astro, you must read this book.",
    },
  ];
  return pages.map(({ slug, title, text }) => {
    return {
      params: { slug },
      props: { title, text },
    };
  });
}

const { title, text } = Astro.props;
---
<html>
  <head>
    <title>{title}</title>
  </head>
  <body>
    <h1>{title}</h1>
    <p>{text}</p>
  </body>
</html>
```

### Режим серверного рендеринга (SSR)
В режиме [SSR](/ru/guides/server-side-rendering/) динамические маршруты определяются точно так же: включите в имена файлов скобки `[param]` или `[...path]` для соответствия произвольным строкам или путям. Но поскольку маршруты больше не строятся заранее, страница будет обслуживаться по любому подходящему маршруту. Поскольку это не "статические" маршруты, `getStaticPaths` не следует использовать.

```astro title="src/pages/resources/[resource]/[id].astro"
---
const { resource, id } = Astro.params;
---
<h1>{resource}: {id}</h1>
```
Эта страница будет предоставлена для любого значения `resource` и `id`: `resources/users/1`, `resources/colors/blue` и т.д.

#### Модификация примера `[...slug]` для SSR

Поскольку страницы SSR не могут использовать `getStaticPaths()`, они не могут получать props. [Предыдущий пример](#пример-динамические-страницы-на-нескольких-уровнях) может быть адаптирован для режима SSR путем поиска значения параметра `slug` в объекте. Если маршрут находится в корне ("/"), параметр slug будет иметь значение `undefined`. Если значение не существует в объекте, мы перенаправляем на страницу 404.

```astro title="src/pages/[...slug].astro"
---
const pages = [
	{
		slug: undefined,
		title: 'Astro Store',
		text: 'Welcome to the Astro store!',
	},
	{
		slug: 'products',
		title: 'Astro products',
		text: 'We have lots of products for you',
	},
	{
		slug: 'products/astro-handbook',
		title: 'The ultimate Astro handbook',
		text: 'If you want to learn Astro, you must read this book.',
	}
];

const { slug } = Astro.params;
const page = pages.find((page) => page.slug === slug);
if (!page) return Astro.redirect("/404");
const { title, text } = page;
---
<html>
<head>
  <title>{title}</title>
</head>
<body>
  <h1>{title}</h1>
  <p>{text}</p>
</body>
</html>
```

## Переадресация

Иногда вам нужно перенаправить читателей на новую страницу, либо постоянно, потому что структура сайта изменилась, либо в ответ на действие, такое как вход в авторизованный маршрут.

Вы можете определить правила для [перенаправления пользователей на постоянно перемещаемые страницы](#настроенные-переадресации) в конфигурации Astro. Или [перенаправлять пользователей динамически](#динамические-переадресации) по мере использования ими вашего сайта.

### Настроенные переадресации

<p><Since v="2.9.0" /></p>

Вы можете указать отображение постоянных переадресаций в конфигурации Astro с помощью значения `redirects`. Для большинства переадресаций это сопоставление старого маршрута с новым маршрутом:

```js title="astro.config.mjs" {4-6}
import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/old-page': '/new-page'
  }
});
```

Эти переадресации подчиняются тем же правилам, что и маршруты на основе файлов. Динамические маршруты разрешены, если новый и старый маршруты содержат одинаковые параметры, например:


```js
{
  "/blog/[...slug]": "/articles/[...slug]"
}
```

Используя SSR или статический адаптер, вы также можете предоставить объект в качестве значения, что позволит вам указать код ответа `status` в дополнение к новому адресу `destination`:

```js title="astro.config.mjs" {5-8}
import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/old-page': {
      status: 302,
      destination: '/new-page'
    }
  }
});
```

При запуске `astro build`, Astro по умолчанию выводит HTML-файлы с тегом [meta refresh](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#examples). Поддерживаемые адаптеры вместо этого будут выводить конфигурационный файл хоста с переадресацией.

По умолчанию код состояния будет `301`. При сборке в HTML-файлы код состояния не используется сервером.

### Динамические переадресации

В глобальном объекте `Astro` метод `Astro.redirect` позволяет динамически перенаправлять на другую страницу. Вы можете сделать это после проверки того, вошел ли пользователь в систему, получив его сессию из куки.

```astro title="src/pages/account.astro" {8}
---
import { isLoggedIn } from '../utils';

const cookie = Astro.request.headers.get('cookie');

// Если пользователь не вошел в систему, перенаправляем его на страницу входа
if (!isLoggedIn(cookie)) {
  return Astro.redirect('/login');
}
---
<html>
  <!-- Page here... -->
</html>
```

## Порядок приоритетов маршрутов

Возможно, что несколько определенных маршрутов будут пытаться построить один и тот же путь URL. Например, все эти маршруты могут построить `/posts/create`:

<FileTree>
- src/pages/
  - [...slug].astro
  - posts/
    - create.astro
    - [page].astro
    - [pid].ts
    - [...slug].astro
</FileTree>

Astro необходимо знать, какой маршрут должен быть использован для создания страницы. Для этого он сортирует их по порядку в соответствии со следующими правилами:

- Маршруты с большим количеством сегментов пути будут иметь приоритет перед менее специфичными маршрутами. В приведенном выше примере все маршруты в разделе `/posts/` имеют приоритет над корневым `/[...slug].astro`.
- Статические маршруты без параметров пути будут иметь приоритет над динамическими маршрутами. Например, `/posts/create.astro` имеет приоритет над всеми остальными маршрутами в примере.
- Динамические маршруты с именованными параметрами имеют приоритет над остальными параметрами. Например, `/posts/[page].astro` имеет приоритет над `/posts/[...slug].astro`.
- Предрендеренные динамические маршруты имеют приоритет над серверными динамическими маршрутами.
- Эндпоинты имеют приоритет над страницами.
- Если ни одно из вышеперечисленных правил не определяет порядок, маршруты сортируются в алфавитном порядке на основе локали по умолчанию вашей установки Node.

Учитывая приведенный выше пример, вот несколько примеров того, как правила будут сопоставлять запрашиваемый URL с маршрутом, используемым для построения HTML:

- `pages/posts/create.astro` - Будет построено только `/posts/create`.
- `pages/posts/[pid].ts` - Будет построено `/posts/abc`, `/posts/xyz` и т.д. Но не `/posts/create`.
- `pages/posts/[page].astro` - Построит `/posts/1`, `/posts/2` и т.д. Но не `/posts/create`, `/posts/abc` и `/posts/xyz`.
- `pages/posts/[...slug].astro` - Будет создавать `/posts/1/2`, `/posts/a/b/c` и т.д. Но не `/posts/create`, `/posts/1`, `/posts/abc` и т.д.
- `pages/[...slug].astro` - Будет создавать `/abc`, `/xyz`, `/abc/xyz` и т.д. Но не `/posts/create`, `/posts/1`, `/posts/abc`, и т.д.

## Пагинация

Astro поддерживает встроенную пагинацию для больших коллекций данных, которые необходимо разбить на несколько страниц. Astro генерирует общие свойства пагинации, включая URL предыдущей/следующей страницы, общее количество страниц и т.д.

Имена пагинационных маршрутов должны использовать тот же синтаксис `[скобка]`, что и стандартные динамические маршруты. Например, имя файла `/astronauts/[page].astro` будет генерировать маршруты для `/astronauts/1`, `/astronauts/2` и т. д., где `[page]` - это номер генерируемой страницы.

Вы можете использовать функцию `paginate()` для генерации этих страниц для массива значений следующим образом:

```astro /{ (paginate) }/ /paginate\\(.*\\)/ /(?<=const.*)(page)/ /page\\.[a-zA-Z]+/
---
// src/pages/astronauts/[page].astro
export async function getStaticPaths({ paginate }) {
  const astronautPages = [{
    astronaut: 'Neil Armstrong',
  }, {
    astronaut: 'Buzz Aldrin',
  }, {
    astronaut: 'Sally Ride',
  }, {
    astronaut: 'John Glenn',
  }];
  // Генерируем страницы из нашего массива астронавтов, по 2 на страницу
  return paginate(astronautPages, { pageSize: 2 });
}
// Все пагинированные данные передаются по пропсу "page"
const { page } = Astro.props;
---

<!--Отображает номер текущей страницы. Также можно использовать Astro.params.page!-->
<h1>Page {page.currentPage}</h1>
<ul>
  <!--Перечисление массива информации об астронавтах-->
  {page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
```

Это генерирует следующие страницы, по 2 элемента на странице:
- `/astronauts/1` - Страница 1: Отображает "Neil Armstrong" и "Buzz Aldrin".
- `/astronauts/2` - Страница 2: отображает "Sally Ride" и "John Glenn".


### Свойство `page`

Когда вы используете функцию `paginate()`, каждой странице будут переданы данные через пропс `page`. Пропс `page` имеет множество полезных свойств, но вот основные из них:
- **page.data** - массив, содержащий фрагмент данных страницы, который вы передали функции `paginate()`.
- **page.url.next** - ссылка на следующую страницу в наборе
- **page.url.prev** - ссылка на предыдущую страницу в наборе

```astro /(?<=const.*)(page)/ /page\\.[a-zA-Z]+(?:\\.(?:prev|next))?/
---
// src/pages/astronauts/[page].astro
// Выводим на страницу тот же список объектов { astronaut }, что и в предыдущем примере
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Page {page.currentPage}</h1>
<ul>
  {page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
{page.url.prev ? <a href={page.url.prev}>Previous</a> : null}
{page.url.next ? <a href={page.url.next}>Next</a> : null}
```


#### Полная справка по API

```ts
interface Page<T = any> {
	/** результат */
	данные: T[];
	/** метаданные */
	/** счетчик первого элемента на странице, начиная с 0 */
	start: number;
	/** счетчик последнего элемента на странице, начиная с 0 */
	end: number;
	/** общее количество результатов */
	total: number;
	/** номер текущей страницы, начиная с 1 */
	currentPage: number;
	/** количество элементов на странице (по умолчанию: 25) */
	size: number;
	/** номер последней страницы */
	lastPage: number;
	url: {
		/** url текущей страницы */
		current: string;
		/** url предыдущей страницы (если она есть) */
		prev: string | undefined;
		/** url следующей страницы (если она есть) */
		next: string | undefined;
	};
}
```

### Вложенная пагинация

Более продвинутым вариантом использования пагинации является **вложенная пагинация.** Это когда пагинация сочетается с другими динамическими параметрами маршрута. Вы можете использовать вложенную пагинацию для группировки коллекции пагинаций по какому-либо свойству или тегу.

Например, если вы хотите сгруппировать посты в Markdown по какому-то тегу, вы можете использовать вложенную пагинацию, создав страницу `/src/pages/[tag]/[page].astro`, которая будет соответствовать следующим URLS:

- `/red/1` (tag=red)
- `/red/2` (tag=red)
- `/blue/1` (tag=blue)
- `/green/1` (tag=green)

Вложенная пагинация работает путем возврата массива результатов `paginate()` из `getStaticPaths()`, по одному для каждой группировки.

В следующем примере мы реализуем вложенную пагинацию для построения URL-адресов, перечисленных выше:

```astro /(?:[(]|=== )(tag)/ "params: { tag }" /const [{ ]*(page|params)/
---
// src/pages/[tag]/[page].astro
export async function getStaticPaths({ paginate }) {
  const allTags = ['red', 'blue', 'green'];
  const allPosts = await Astro.glob('../../posts/*.md');
   // Для каждого тега возвращаем результат paginate().
  // Убедитесь, что вы передали `{params: {tag}}` в `paginate()`.
  // чтобы Astro знал, для какой группы тегов получен результат.
  return allTags.flatMap((tag) => {
    const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
    return paginate(filteredPosts, {
      params: { tag },
      pageSize: 10
    });
  });
}
const { page } = Astro.props;
const params = Astro.params;
```

## Исключение страниц

Вы можете исключить страницы или каталоги из сборки, добавив к их именам символ подчеркивания (`_`). Файлы с префиксом `_` не будут распознаны маршрутизатором и не будут помещены в каталог `dist/`.

Это можно использовать для временного отключения страниц, а также для размещения тестов, утилит и компонентов в той же папке, что и связанные с ними страницы. 

В этом примере только `src/pages/index.astro` и `src/pages/posts/post1.md` будут построены как маршруты страниц и HTML-файлы.


<FileTree>
- src/pages/
  - _hidden-directory/
    - page1.md
    - page2.md
  - _hidden-page.astro
  - **index.astro**
  - posts/
    - _SomeComponent.astro
    - _utils.js
    - **post1.md**
</FileTree>